using System;
using System.Globalization;
using System.IO;

using Atomic.Libraries;

namespace Atomic.Vasp.Options
{
	/// <summary>
	/// Automatic Monkhorst-Pack k-point mesh (KPOINTS file).
	/// </summary>
	[Serializable]
	public class MonkhorstPackMesh : VaspOption
	{
		/// <summary>
		/// Fully automatic Monkhorst-Pack k-point mesh. Number of k-points is determined by the size of the reciprocal cell. Useful values for the length vary
		/// between 10 (large gap insulators) and 100 (d-metals).
		/// http://cms.mpi.univie.ac.at/vasp/vasp/Automatic_k_mesh_generation.html
		/// </summary>
		public MonkhorstPackMesh(double length)
		{
			KPoints = new ReadOnlyList<string>(new string[] { "K-Points", "0".PadRight(15) + " ! 0 = Automatic generation scheme", "Auto".PadRight(15) + " ! Fully automatic", length.ToString(CultureInfo.InvariantCulture).PadRight(15) + " ! Length" } );
		}

		/// <summary>
		/// Automatic Monkhorst-Pack k-point mesh requiring only the input of a division of the Brillouin zone in each direction for the k-mesh to be produced.
		/// http://cms.mpi.univie.ac.at/vasp/guide/node57.html
		/// </summary>
		public MonkhorstPackMesh(int n1, int n2, int n3)
			: this(n1, n2, n3, 0.0, 0.0, 0.0)
		{
		}

		/// <summary>
		/// Automatic Monkhorst-Pack k-point mesh requiring only the input of a division of the Brillouin zone in each direction and the origin (some shift) for the k-mesh to be produced.
		/// http://cms.mpi.univie.ac.at/vasp/guide/node57.html
		/// </summary>
		public MonkhorstPackMesh(int n1, int n2, int n3, double s1, double s2, double s3)
		{
			KPoints = new ReadOnlyList<string>(new string[] { "K-Points", "0".PadRight(15) + " ! 0 = Automatic generation scheme", "Monkhorst-Pack", string.Format("{0} {1} {2}", n1, n2, n3).PadRight(15) + " ! Numbers for the subdivisions along reciprocal lattice vectors", string.Format("{0:r} {1:r} {2:r}", s1, s2, s3).PadRight(15) + " ! Optional shift of the mesh" } );
		}

		public override void Write(VaspIncar incar, DirectoryInfo directory)
		{
			Write(Path.Combine(directory.FullName, "KPOINTS"));
		}

		private void Write(string fileName)
		{
			File.WriteAllLines(fileName, KPoints);
		}

		public ReadOnlyList<string> KPoints
		{
			get;
			private set;
		}
	}
}
